using System.Collections;
using Slaks.VectorBasics.Comparators;
using Slaks.VectorBasics.Containers;

namespace Slaks.VectorBasics
{
	public class Vector
	{
		private string m_name;
		private string m_category;
		private bool m_isCategorySet = false;
		private Id2VectorItemMap m_id2VectorItemMap;
		private VectorItemList m_vectorItemList;

		public Vector(string vectorName)
		{
			m_name = vectorName;
			m_id2VectorItemMap = new Id2VectorItemMap();
			m_vectorItemList = new VectorItemList();
		}

		public Vector(string vectorName, string category)
		{
			m_name = vectorName;
			this.Category = category;
			m_id2VectorItemMap = new Id2VectorItemMap();
			m_vectorItemList = new VectorItemList();
		}

		public string Name
		{
			get { return m_name; }
			set { m_name = value; }
		}

		public string Category
		{
			get { return m_category; }
			set
			{
				m_category = value;
				m_isCategorySet = true;
			}
		}

		public bool IsCategorySet()
		{
			return m_isCategorySet;
		}

		public VectorItemList GetVectorItemList()
		{
			return m_vectorItemList;
		}

		public int GetVectorLength()
		{
			return m_vectorItemList.Count;
		}

		public VectorItem GetVectorItem(long id)
		{
			if (m_id2VectorItemMap.Contains(id)) return m_id2VectorItemMap[id];
			return null;
		}

		public bool AddVectorItem(VectorItem vectorItem)
		{
			if (m_id2VectorItemMap.Contains(vectorItem.GetId())) return false;
			m_id2VectorItemMap.Add(vectorItem.GetId(), vectorItem);
			m_vectorItemList.Add(vectorItem);
			return true;
		}

		/// <summary>
		/// Create the vertex with specified id. <br>
		/// If the vertex already exists then return this vertex otherwise create new, add to graph and return  the vertex
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public VectorItem CreateAddVectorItem(long id)
		{
			VectorItem item = GetVectorItem(id);
			if (item != null) return item;
			item = new VectorItem(id);
			m_id2VectorItemMap.Add(item.GetId(), item);
			m_vectorItemList.Add(item);
			return item;
		}

		public void RemoveInfrequentVectorItems(int numberOfVectorItemsToLeave)
		{
			if (numberOfVectorItemsToLeave <= 0) return;
			int totalCount = m_vectorItemList.Count;
			if (numberOfVectorItemsToLeave >= totalCount) return;
			//what is desired length of the vertex list

			SortVectorItems(new FrequencyComparer());

			int currentIndex = numberOfVectorItemsToLeave;

			long idToRemove;
			while (m_vectorItemList.Count > numberOfVectorItemsToLeave)
			{
				idToRemove = m_vectorItemList[currentIndex].GetId();
				m_vectorItemList.RemoveAt(currentIndex);
				m_id2VectorItemMap.Remove(idToRemove);
			}

		}

		#region sort

		/// <summary>
		/// Sort vector by its vector item IDS
		/// </summary>
		public void SortVectorItems()
		{
			m_vectorItemList.Sort();
		}

		/// <summary>
		/// Sort vector providing custom comparer
		/// </summary>
		/// <param name="comparer"></param>
		public void SortVectorItems(IComparer comparer)
		{
			m_vectorItemList.Sort(comparer);
		}

		#endregion
	}
}